<?php
/**
 * YICMS
 * ============================================================================
 * 版权所有 2014-2017 YICMS，并保留所有权利。
 * 网站地址: http://www.yicms.vip
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * Created by PhpStorm.
 * Author: kenuo
 * Date: 2017/11/17
 * Time: 下午4:38
 */

namespace App\Services\PayAndConsume;

use App\Repositories\PayAndConsume\StatRepository;
use \Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Auth;

class StatService
{
    /**
     * ActionLogsService constructor.
     * @param $actionLogsRepository
     */
    public function __construct(StatRepository $statRepository)
    {
        $this->statRepository = $statRepository;
    }

    /**
     * 根据服务器ID获取统计信息
     */
    public function getStatByUniqueID($uniqueID, $startTime, $endTime)
    {
        if (count($uniqueID) <= 0) {
            return [];
        }

        $stat = $this->statRepository->getWithStat($uniqueID, $startTime, $endTime);
        $temp = [];

        //根据date合并结果集
        foreach ($stat as $key => $value) {
            $date = $value['date'];
            $temp[$date][] = $value;
        }
        $stat = [];

        //求同一天,各个服务器相关字段值的和
        $arr = ['active_users', 'amounts', 'new_pay_amounts', 'new_pay_users', 'new_users', 'old_users', 'pay_users', 'pay_times', 'old_pay_users', 'old_pay_amounts'];
        foreach ($temp as $key => $value) {
            foreach ($arr as $i => $j) {
                $stat[$key][$j] = array_sum(array_column($value, $j));
            }
            $stat[$key]['date'] = $key;
        }

        //计算百分比结果
        if (count($stat) > 0) {
            foreach ($stat as $key => $value) {
                $stat[$key]['arppu'] = ($value['pay_users'] > 0) ? round($value['amounts'] / $value['pay_users'], 2) : 0;
                $stat[$key]['arpu'] = ($value['active_users'] > 0) ? round($value['amounts'] / $value['active_users'], 2) : 0;
                $stat[$key]['active_pay_rate'] = ($value['active_users'] > 0) ? round($value['pay_users'] / $value['active_users'] * 100, 2) . '%' : 0;
                $stat[$key]['new_user_pay_rate'] = ($value['new_users'] > 0) ? round($value['new_pay_users'] / $value['new_users'] * 100, 2) . '%' : 0;
                $stat[$key]['new_user_arppu'] = ($value['new_pay_users'] > 0) ? round($value['new_pay_amounts'] / $value['new_pay_users'], 2) : 0;
                $stat[$key]['new_user_arpu'] = ($value['new_users'] > 0) ? round($value['new_pay_amounts'] / $value['new_users'], 2) : 0;
                $stat[$key]['old_user_arppu'] = ($value['old_pay_users'] > 0) ? round($value['old_pay_amounts'] / $value['old_pay_users'], 2) : 0;
                $stat[$key]['old_user_arpu'] = ($value['old_users'] > 0) ? round($value['old_pay_amounts'] / $value['old_users'], 2) : 0;
                $stat[$key]['old_user_pay_rate'] = ($value['old_users'] > 0) ? round($value['old_pay_users'] / $value['old_users'] * 100, 2) . '%' : 0;
            }
        }

        krsort($stat);
        return $stat;
    }

    /**
     * 根据服务器ID获取 留存率
     */
    public function getRetentionByUniqueID($uniqueID, $startTime, $endTime)
    {
        if (count($uniqueID) <= 0) {
            return [];
        }

        $retention = $this->statRepository->getWithRentention($uniqueID, $startTime, $endTime);
        $temp = [];
        $logDay = config('enums.retention_log_day');
        //根据date合并结果集
        foreach ($retention as $key => $value) {
            $date = $value['date'];
            $temp[$date][] = $value;
            $temp[$date]['date'] = $date;
        }
        unset($retention);

        //拿到新用户和老用户总数
        $stat = $this->getStatByUniqueID($uniqueID, $startTime, $endTime);
        foreach ($temp as $key => $value) {
            $temp[$key]['new_users'] = (isset($stat[$key]) ? $stat[$key]['new_users'] : '0');
            $temp[$key]['old_users'] = (isset($stat[$key]) ? $stat[$key]['old_users'] : '0');
        }

        //求同一天,各个服务器相关字段值的和
        foreach ($temp as $key => $value) {
            foreach ($logDay as $i => $j) {
                $amount = array_sum(array_column($value, 'day_' . $j . '_active_users'));
                if ($amount > 0 && $value['new_users'] > 0) {
                    $temp[$key]['day_' . $j . '_active_users'] = round($amount / $value['new_users'] * 100, 2) . '%';
                } else {
                    $temp[$key]['day_' . $j . '_active_users'] = '0';
                }
            }
        }

        ksort($temp);
        return $temp;
    }

    /**
     * 根据服务器ID获取 ltv
     */
    public function getLtvByUniqueID($uniqueID, $startTime, $endTime)
    {
        $ltv = $this->statRepository->getWithLtv($uniqueID, $startTime, $endTime);
        $temp = [];
        $logDay = config('enums.ltv_log_day');
        //根据date合并结果集
        foreach ($ltv as $key => $value) {
            $date = $value['date'];
            $temp[$date][] = $value;
            $temp[$date]['date'] = $date;
        }
        unset($ltv);

        //拿到新用户和老用户总数
        $stat = $this->getStatByUniqueID($uniqueID, $startTime, $endTime);
        foreach ($temp as $key => $value) {
            $temp[$key]['new_users'] = (isset($stat[$key]) ? $stat[$key]['new_users'] : '0');
        }

        //求同一天,各个服务器相关字段值的和
        foreach ($temp as $key => $value) {
            $inc = 0;
            foreach ($logDay as $i => $j) {
                $amount = array_sum(array_column($value, 'day_' . $j . '_amounts'));
                $inc += $amount;

                if ($amount > 0 && $value['new_users'] > 0) {
                    $temp[$key]['day_' . $j . '_amounts'] = round($inc / $value['new_users'], 2);
                } else {
                    $temp[$key]['day_' . $j . '_amounts'] = '0';
                }
            }
        }

        ksort($temp);
        return $temp;
    }

    /**
     * 根据服务器ID获取    单服充值情况
     */
    private function getServerByUniqueID($uniqueID, $startTime)
    {
        $stat = $this->statRepository->getWithStat($uniqueID, $startTime, $startTime);

        $temp = [];
        //根据date合并结果集
        foreach ($stat as $key => $value) {
            $unique_id = $value['unique_id'];
            $temp[$unique_id] = $value->toArray();
        }
        unset($stat);

        //计算百分比结果
        if (count($temp) > 0) {
            foreach ($temp as $key => $value) {
                $temp[$key]['arppu'] = $value['pay_users'] > 0 ? round($value['amounts'] / $value['pay_users'], 2) : 0;
                $temp[$key]['arpu'] = $value['active_users'] > 0 ? round($value['amounts'] / $value['active_users'], 2) : 0;
            }
        }

        $amounts = array_column($temp, 'amounts');
        array_multisort($amounts, SORT_DESC, $temp);

        return $temp;
    }

    /**
     * 根据服务器ID获取  合并昨天和今天  单服充值情况
     */
    public function getMergeServerByUniqueID($request)
    {
        $today = $this->getServerByUniqueID($request['unique_id'], $request['start_time']);
        $yesterday = $this->getServerByUniqueID(array_keys($today), date('Y-m-d', strtotime($request['start_time'] . ' -1 days')));

        foreach ($today as $key => $value) {
            if (isset($yesterday[$key])) {
                $today[$key]['yesterday_pay_users'] = $yesterday[$key]['pay_users'];
                $today[$key]['yesterday_arpu'] = $yesterday[$key]['arpu'];
                $today[$key]['yesterday_arppu'] = $yesterday[$key]['arppu'];
            } else {
                $today[$key]['yesterday_pay_users'] = '-';
                $today[$key]['yesterday_arpu'] = '-';
                $today[$key]['yesterday_arppu'] = '-';
            }
        }

        //分页
        $currentPage = LengthAwarePaginator::resolveCurrentPage();
        $perPage = $request['page_size'];
        $offset = ($currentPage * $perPage) - $perPage;
        $data = new LengthAwarePaginator(array_slice($today, $offset, $perPage, true), count($today), $perPage,
            $currentPage, ['path' => $request->url(), 'query' => $request->query()]);
        return $data;
    }

    /**
     * 获取 渠道统计信息
     */
    public function getChannelStat($request)
    {
        $channelsAuth = Auth::guard('admin')->user()->getChannels(['game_id' => session('game_id')], 'channel_id');
        $channelsAuth = array_keys($channelsAuth);
        $channelsAuth = array_map('strval', $channelsAuth);

        //新增用户
        $newUsers = $this->statRepository->getChannelNewUsers($request, $channelsAuth)->toArray();
        $newUsers = array_combine(array_column($newUsers, '_id'), $newUsers);
        //活跃用户
        $activeUsers = $this->statRepository->getChannelActiveUsers($request, $channelsAuth)->toArray();
        $activeUsers = array_combine(array_column($activeUsers, '_id'), $activeUsers);
        //活跃付费用户
        $payUsers = $this->statRepository->getChannelPayUsers($request, $channelsAuth)->toArray();
        $payUsers = array_combine(array_column($payUsers, '_id'), $payUsers);
        //总收入
        $totalAmounts = $this->statRepository->getChannelTotalAmounts($request, $channelsAuth)->toArray();
        $totalAmounts = array_combine(array_column($totalAmounts, '_id'), $totalAmounts);

        foreach ($activeUsers as $key => $value) {
            $activeUsers[$key]['new_users'] = isset($newUsers[$key]) ? $newUsers[$key]['new_users'] : 0;
            $activeUsers[$key]['total_amounts'] = isset($totalAmounts[$key]) ? $totalAmounts[$key]['total_amounts'] : 0;
            $activeUsers[$key]['pay_users'] = isset($payUsers[$key]) ? $payUsers[$key]['pay_users'] : 0;

            //活跃付费率=活跃付费用户/活跃用户
            $activeUsers[$key]['active_pay_rate'] = (($activeUsers[$key]['active_users'] > 0) ? round($activeUsers[$key]['pay_users'] / $activeUsers[$key]['active_users'] * 100, 2) . '%' : 0);
            //ARPU=总收入/活跃用户
            $activeUsers[$key]['arpu'] = (($activeUsers[$key]['active_users'] > 0) ? round($activeUsers[$key]['total_amounts'] / $activeUsers[$key]['active_users'], 2) : 0);
            //ARPPU=总收入/活跃付费用户
            $activeUsers[$key]['arppu'] = (($activeUsers[$key]['pay_users'] > 0) ? round($activeUsers[$key]['total_amounts'] / $activeUsers[$key]['pay_users'], 2) : 0);
        }

        rsort($activeUsers);

        return $activeUsers;
    }

    /**
     * 获取 分时在线人数
     */
    public function getOnline($request, &$time, &$legendData, &$data)
    {
        if (count($request['unique_id']) <= 0) {
            $legendData = json_encode($legendData, JSON_UNESCAPED_UNICODE);
            return '[]';
        }

        $data = $this->statRepository->getOnline($request['start_time'], $request['end_time'], $request['unique_id'])->toArray();

        $time = json_encode(array_column($data, '_id'), JSON_UNESCAPED_UNICODE);
        $todayAmounts = array_column($data, 'total_amounts');
        $series[] = [
            'name' => '在线人数',
            'type' => 'line',
            'data' => $todayAmounts,
            'markLine' => [
                'data' => [
                    ['type' => 'average', 'name' => '平均值']
                ],
            ]
        ];

        $yesterdayAmounts = '[]';
        if ($request['start_time'] == $request['end_time']) {
            $legendData[] = '昨日在线人数';
            $yesterdayStartTime = date('Y-m-d', strtotime($request['start_time'] . ' - 1 days'));
            $yesterdayEndTime = date('Y-m-d', strtotime($request['end_time'] . ' - 1 days'));
            $yesterdayData = $this->statRepository->getOnline($yesterdayStartTime, $yesterdayEndTime, $request['unique_id'])->toArray();
            $yesterdayAmounts = array_column($yesterdayData, 'total_amounts');
            $series[] = [
                'name' => '昨日在线人数',
                'type' => 'line',
                'data' => $yesterdayAmounts,
                'markLine' => [
                    'data' => [
                        ['type' => 'average', 'name' => '平均值']
                    ],
                ]
            ];
        }

        $time = json_encode(array_column($data, '_id'), JSON_UNESCAPED_UNICODE);
        $legendData = json_encode($legendData, JSON_UNESCAPED_UNICODE);
        $series = json_encode($series, JSON_UNESCAPED_UNICODE);

        return $series;
    }

    /**
     * 获取 实时在线情况
     */
    public function getLiveOnline($request, &$time, &$max, &$avg)
    {
        $data = $this->statRepository->getLiveOnline($request['start_time'], $request['end_time'], $request['unique_id'])->toArray();

        if (count($data) > 0) {
            $time = json_encode(array_column($data, 'register_time'), JSON_UNESCAPED_UNICODE);
            $max = json_encode(array_column($data, 'rush_hour'), JSON_UNESCAPED_UNICODE);
            $avg = json_encode(array_column($data, 'avg_amounts'), JSON_UNESCAPED_UNICODE);
        }

        return $data;
    }

    /**
     * 获取 玩家等级分布
     */
    public function getUserLevel($request, &$levelX, &$amountY, &$totalActiveUsers)
    {
        $data = $this->statRepository->getUserLevel($request['start_time'], $request['end_time'], $request['unique_id'])->toArray();
        $totalActiveUsers = array_sum(array_column($data, 'sum_active_users'));//总活跃账户数

        if (count($data) > 0) {
            $level = range(5, 300, 5);
            $level = array_fill_keys($level, 0);

            foreach ($data as $key => $value) {
                //$value['_id'] 是数据库中玩家的等级
                $levelKey = intval(ceil($value['_id'] / 5) * 5);
                $level[$levelKey] += $value['sum_active_users'];
            }


            foreach ($level as $key => $value) {
                $level[($key - 4) . '~' . $key] = $value;
                unset($level[$key]);
            }

            $levelX = json_encode(array_keys($level), JSON_UNESCAPED_UNICODE);
            $amountY = json_encode(array_values($level), JSON_UNESCAPED_UNICODE);
        }

        return $data;
    }
}